/*
在空对象模式（Null Object Pattern）中，一个空对象取代 NULL 对象实例的检查。
Null 对象不是检查空值，而是反应一个不做任何动作的关系。
这样的 Null 对象也可以在数据不可用的时候提供默认的行为。
在空对象模式中，我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类，
还创建一个未对该类做任何实现的空对象类，
该空对象类将无缝地使用在需要检查空值的地方。
*/

#include <memory>
#include <string>
#include <iostream>

#if 0
__interface Book
{
    bool IsNull();  //添加判断Book对象是否为空对象
    void show();   //展示图书信息
};
#else
class Book
{
public:
    Book(){}
    virtual ~Book(){}
    virtual bool IsNull() = 0;  //添加判断Book对象是否为空对象
    virtual void show() = 0;   //展示图书信息
};
#endif

class ConcreteBook :public Book
{
public:
    ConcreteBook(int id, const std::string &_name, const std::string &_author)
        :ID(id)
        , name(_name)
        , author(_author)
    {}

    void show()
    {
        std::cout << ID << "**" << name << "&&" << author << std::endl;
    }
    bool IsNull()
    {
        return false;
    }
private:
    int ID;
    std::string  name;
    std::string  author;
};

class NullBook : public Book
{
public :
    bool IsNull()
    {
        return true;
    }

    void show()
    {
        std::cout <<"Sorry, 未找到ID对应的图书,请再次输入 " << std::endl;
    }

};

class BookFactory//图书 工厂
{
public :
    std::shared_ptr<Book> getBook(int id)
    {
        std::shared_ptr<Book> spBook;
        switch (id)
        {
        case 1:
            spBook = std::make_shared<ConcreteBook>(id, "设计模式", "GOF");
            break;
        case 2:
            spBook = std::make_shared<ConcreteBook>(id, "Head First", "设计模式");
            break;
        default:
            spBook = std::make_shared<NullBook>();  //创建一个NullBook 对象
            break;
        }
        return spBook;
    }

};

int main()
{
    std::shared_ptr<BookFactory> spBookFactory(new BookFactory());
    std::shared_ptr<Book> spBook = spBookFactory->getBook(1);
    spBook->show();

    spBook = spBookFactory->getBook(2);
    spBook->show();

    spBook = spBookFactory->getBook(3);
    spBook->show();

    return 0;
}
